It looks like Raustats might not be what I am looking for to get SLA level census data quickly. Let’s try Census2016 from Hugh Parsonage.

rr full_2016_census <- Census2016_wide_by_SA2_year %>% filter(year == ‘2016’ ) head(full_2016_census)

Yes - this is what I need.

Loading other tables

rr ancestories_2016 <- Census2016_ancestories %>% filter(year == ‘2016’ ) countries_of_birth_2016 <- Census2016_countries_of_birth %>% filter(year == ‘2016’ ) languages_2016 <- Census2016_languages %>% filter(year == ‘2016’ ) religions_2016 <- Census2016_religions %>% filter(year == ‘2016’ )

Feature Engineering

Each of the four variables ancestory, country of birth, languages and religions are quite granular, and it may make sense to look at these variables at a lower level of granularity.

Ancestory:

rr download.file(‘https://www.abs.gov.au/AUSSTATS/subscriber.nsf/log?openagent&12490do0001_201912.xls&1249.0&Data%20Cubes&674EFC4CA0A3D8FDCA2584D30012B905&0&2019&18.12.2019&Latest’, ‘./Data/ancestry_classification.xls’, method = ‘libcurl’)

ancestry_classification_4dig <- readxl::read_xls(‘./Data/ancestry_classification.xls’, sheet = ‘Table 1.3’, skip = 7, col_names = c(‘X1’, ‘X2’, ‘Ancestory_Code_4’, ‘Ancestory’)) %>% filter(!is.na(Ancestory)) %>% select(Ancestory_Code_4, Ancestory)

ancestry_classification_1dig <- readxl::read_xls(‘./Data/ancestry_classification.xls’, sheet = ‘Table 1.1’, skip = 5, col_names = c(‘Ancestory_Code_1’, ‘Ancestory_Group’))%>% filter(!is.na(Ancestory_Group))

Country of birth

rr download.file(‘https://www.abs.gov.au/ausstats/subscriber.nsf/log?openagent&sacc_12690do0001_201903.xls&1269.0&Data%20Cubes&480BD730AF42D515CA2583BD007707C5&0&2016&15.03.2019&Latest’, ‘./Data/country_classification.xls’, method = ‘libcurl’)

country_classification_4dig <- readxl::read_xls(‘./Data/country_classification.xls’, sheet = ‘Table 1.3’, skip = 7, col_names = c(‘X1’, ‘X2’, ‘Country_Code_4’, ‘Country’)) %>% filter(!is.na(Country)) %>% select(-X1, -X2)

country_classification_2dig <- readxl::read_xls(‘./Data/country_classification.xls’, sheet = ‘Table 1.2’, skip = 6, col_names = c(‘X1’, ‘Country_Code_2’, ‘Country_Name_2’)) %>% filter(!is.na(Country_Name_2)) %>% select(-X1)

country_classification_1dig <- readxl::read_xls(‘./Data/country_classification.xls’, sheet = ‘Table 1.1’, skip = 5, col_names = c(‘Country_Code_1’, ‘Country_Group’)) %>% filter(!is.na(Country_Group))

Language

rr download.file(‘https://www.abs.gov.au/AUSSTATS/subscriber.nsf/log?openagent&ASCL_12670DO0001_201703.xls&1267.0&Data%20Cubes&F84620CF6E13F7E8CA257FF1001E68A7&0&2016&28.03.2017&Latest’, ‘./Data/language_classification.xls’, method = ‘libcurl’)

language_classification_4dig <- readxl::read_xls(‘./Data/language_classification.xls’, sheet = ‘Table 1.3’, skip = 8, col_names = c(‘X1’, ‘X2’, ‘X3’, ‘X4’, ‘Language_Code_3’, ‘Language’)) %>% filter(!is.na(Language)) %>% select(-X1, -X2, -X3, -X4)

language_classification_1dig <- readxl::read_xls(‘./Data/language_classification.xls’, sheet = ‘Table 1.1’, skip = 5, col_names = c(‘Language_Code_1’, ‘Language_Group’)) %>% filter(!is.na(Language_Group))

Religion

rr download.file(‘https://www.abs.gov.au/AUSSTATS/subscriber.nsf/log?openagent&ASCRG_12660DO0001_201707.xls&1266.0&Data%20Cubes&B3EAFE3FE6180D37CA257FF1001E673C&0&2016&14.07.2017&Latest’, ‘./Data/religion_classification.xls’, method = ‘libcurl’)

religion_classification_3dig <- readxl::read_xls(‘./Data/religion_classification.xls’, sheet = ‘Table 1.2’, skip = 6, col_names = c(‘X1’, ‘Religion_Code_3’, ‘Religion’)) %>% filter(!is.na(Religion)) %>% select(-X1)

religion_classification_1dig <- readxl::read_xls(‘./Data/religion_classification.xls’, sheet = ‘Table 1.1’, skip = 5, col_names = c(‘Religion_Code_1’, ‘Religion_Group’)) %>% filter(!is.na(Religion_Group))

Combine with election data

Aggregate at the SA2 level - add unless variable contains median, average, persons_per_bedroom

census_2016_all_vars <- Census2016_wide_by_SA2_year %>% 
  filter(year == '2016') %>% 
  rowwise() %>% 
  mutate(sa2_id = paste0(substr(sa2_code, 1, 1), substr(sa2_code, 6, 9))) %>% 
  filter(isMissing == FALSE) %>% 
  mutate(percent_female = female/persons,
         percent_defacto = defacto_persons/persons,
         percent_married = married_persons/persons,
         percent_indig = indig_persons/persons,
         percent_born_in_australia = born_in_australia/persons,
         percent_unit = flat_or_unit/n_dwellings,
         percent_mortgage = dwelling_owned_mortgage/n_dwellings,
         percent_rent = dwelling_rented/n_dwellings)


census_2016_means <- census_2016_all_vars %>% 
  select(median_age, median_household_income, average_household_size, 
         persons_per_bedroom, median_weekly_rent, median_annual_mortgage, sa2_id) %>% 
  group_by(sa2_id) %>% 
  summarise_all(mean, na.rm = TRUE)

census_2016_counts <- census_2016_all_vars %>% 
  select(n_dwellings, persons, female, male, 
         married_persons, married_females, married_males, defacto_persons, 
         defacto_females, defacto_males, notmarried_persons, 
         notmarried_females, notmarried_males, indig_persons, 
         indig_males, indig_females, non_indig_persons, 
         non_indig_females, non_indig_males, not_stated_indig_persons, 
         not_stated_indig_males, not_stated_indig_females, 
         born_in_australia, born_overseas, country_not_stated, 
         separate_house, flat_or_unit, housing_other_or_not_stated, semi_or_townhouse, 
         dwelling_owned_outright, dwelling_owned_mortgage, dwelling_other_or_not_stated,
         dwelling_rented, sa2_id) %>% 
  group_by(sa2_id) %>% 
  summarise_all(sum, na.rm = TRUE) %>% 
  mutate(percent_female = female/persons,
         percent_defacto = defacto_persons/persons,
         percent_married = married_persons/persons,
         percent_indig = indig_persons/persons,
         percent_born_in_australia = born_in_australia/persons,
         percent_unit = flat_or_unit/n_dwellings,
         percent_mortgage = dwelling_owned_mortgage/n_dwellings,
         percent_rent = dwelling_rented/n_dwellings)

So what I need is weighted demographic data for each of the polling places based on the number of people from each SLA2 who voted at the polling place. Since we don’t know who voted where, and who can vote at all, we are making the naive assumptions that * Voters at each SLA are similar * Voters are representitive of census respondents at the SLA2 level.

Download and load polling places by SA1


download.file('https://www.aec.gov.au/Elections/Federal_Elections/2016/files/polling-place-by-sa1s-2016.xlsx', './Data/polling-place-by-sa1s-2016.xlsx', method = 'libcurl')
trying URL 'https://www.aec.gov.au/Elections/Federal_Elections/2016/files/polling-place-by-sa1s-2016.xlsx'
Content type 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' length 31087463 bytes (29.6 MB)
==================================================
downloaded 29.6 MB
polling_place_data <- readxl::read_xlsx('./Data/polling-place-by-sa1s-2016.xlsx')

Aggregate polling place data to SA2

rr polling_place_sa2 <- polling_place_data %>% mutate(sa2_id = floor(SA1_id / 100)) %>% group_by(year, state_ab, div_nm, pp_id, pp_nm, sa2_id) %>% summarise(votes = sum(votes))

Combine with demographic data and aggregate

polling_place_demog <- polling_place_sa2 %>% 
  mutate(sa2_id = as.character(sa2_id)) %>% 
  inner_join(census_2016_all_vars)

polling_place_demog_means <- polling_place_demog %>% 
  select(year, state_ab, div_nm, pp_id, pp_nm, sa2_id, votes,
         median_age, median_household_income, average_household_size, 
         persons_per_bedroom, median_weekly_rent, median_annual_mortgage,
         percent_female, percent_defacto, percent_married, percent_indig, 
         percent_born_in_australia, percent_unit, percent_mortgage, percent_rent) %>% 
  group_by(year, state_ab, div_nm, pp_id, pp_nm) %>% 
  summarise_at(vars(median_age, median_household_income, 
                    average_household_size, persons_per_bedroom, median_weekly_rent, 
                    median_annual_mortgage, percent_female, percent_defacto, 
                    percent_married, percent_indig, percent_born_in_australia,
                    percent_unit, percent_mortgage, 
                    percent_rent), funs(weighted.mean(., w=votes)))

Add in 2pp at the polling booth level

rr election_2pp <- twoparty_pollingbooth_download()

trying URL 'https://github.com/ropenscilabs/eechidna/raw/master/extra-data/tpp_pp.rda'
Content type 'application/octet-stream' length 1677810 bytes (1.6 MB)
==================================================
downloaded 1.6 MB

rr polling_place_2pp <- polling_place_demog_means %>% group_by() %>% rename(StateAb = state_ab, DivisionNm = div_nm, PollingPlace = pp_nm) %>% mutate(DivisionNm = toupper(DivisionNm), PollingPlace = toupper(PollingPlace)) %>% left_join(election_2pp %>% filter(year == 2016))

Joining, by = c(\year\, \StateAb\, \DivisionNm\, \PollingPlace\)

Check for missing data

polling_place_2pp %>% 
  summarise_all(funs(sum(is.na(.))))

Which booths are null?

polling_place_2pp %>% 
  filter(is.na(TotalVotes)) %>% 
  tabyl(PollingPlace)
 PollingPlace   n percent
       ABSENT 150    0.25
       POSTAL 150    0.25
     PRE-POLL 150    0.25
  PROVISIONAL 150    0.25

So the Absent, Postals, Pre-Poll and Provisional votes aren’t in this table. Let’s come back to those…

polling_place_2pp %>% 
  summarise_all(funs(sum(is.null(.))))

Remove the rows with NAs

polling_place_2pp_clean <- polling_place_2pp %>% 
  filter(!is.na(TotalVotes))
polling_place_2pp_clean %>% 
  summarise_all(funs(sum(is.na(.))))

Which polling stations have missing data? Not too concerned about post code, as there are some special booths

polling_place_2pp_clean %>% 
  filter(is.na(median_age)|is.na(Latitude))

Looks like mobile teams and prepoll centres, and only latitude and longitude. Will remove the Brand mobile team, as the demographic data does not look valid.

polling_place_2pp_clean<- polling_place_2pp_clean %>% 
  dplyr::filter(PollingPlaceID != 65161)

Visualising Basic Statistics

polling_place_2pp_clean %>% 
  ggplot(aes(x = LNP_Percent/100)) + stat_density(geom="line", colour = 'blue') +
  theme_classic(base_size = 16) +
  scale_x_continuous(labels=scales::percent) +
  labs(title = '2016 Election: LNP 2 Party Preferred Percentage', x = '2PP Percentage', 
       y = 'Density', subtitle = 'by Polling Booth, Unweighted')

polling_place_2pp_clean %>% 
  ggplot(aes(x = ALP_Percent/100)) + stat_density(geom="line", colour = 'red') +
  theme_classic(base_size = 16) +
  scale_x_continuous(labels=scales::percent) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', x = '2PP Percentage', 
       y = 'Density', subtitle = 'by Polling Booth, Unweighted')

polling_place_2pp_clean %>% 
  ggplot(aes(x = Swing/100)) + stat_density(geom="line", colour = 'purple') +
  theme_classic(base_size = 16) +
  scale_x_continuous(labels=scales::percent) +
  labs(title = '2016 Election: Swing to Incumbent', x = 'Swing', 
       y = 'Density', subtitle = 'by Polling Booth, Unweighted')

polling_place_2pp_clean %>% 
  ggplot(aes(x = median_household_income)) + stat_density(geom="line", colour = 'purple') +
  theme_classic(base_size = 16) +
  scale_x_continuous(labels=scales::dollar) +
  labs(title = '2016 Census: Median Income', x = 'Median Income', 
       y = 'Density', subtitle = 'by Polling Booth, Unweighted')

State Breakdowns

Can we look at these distributions by state?

polling_place_2pp_clean %>% 
  ggplot(aes(x = ALP_Percent/100, colour = StateAb)) + 
  stat_density(geom="line", position = 'dodge') +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  scale_x_continuous(labels=scales::percent) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', x = '2PP Percentage', 
       y = 'Frequency', subtitle = 'by Polling Booth, Unweighted')

What about by median income

polling_place_2pp_clean %>%
  ggplot(aes(y = ALP_Percent/100, x = median_household_income, colour = StateAb)) +
  geom_point() +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::dollar) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', x = 'Booth Median Income',
       y = 'ALP 2pp Percentage', subtitle = 'by Polling Booth, Unweighted') +
  facet_wrap(~StateAb, nrow = 4)

What about comparing NSW electorates? There seems to be an odd separation in income bands for low ALP 2pp. Could this be a regional vs city difference?

fp_booth_16 <- firstpref_pollingbooth_download() %>% 
  filter(year == 2016)
trying URL 'https://github.com/ropenscilabs/eechidna/raw/master/extra-data/fp_pp.rda'
Content type 'application/octet-stream' length 3227934 bytes (3.1 MB)
==================================================
downloaded 3.1 MB
polling_2cp <- read_csv('https://results.aec.gov.au/20499/Website/Downloads/HouseTcpByCandidateByPollingPlaceDownload-20499.csv', skip = 1)

polling_2pp <- read_csv('https://results.aec.gov.au/20499/Website/Downloads/HouseTppByPollingPlaceDownload-20499.csv', skip = 1)

fp_booth_2016 <- read_csv('https://results.aec.gov.au/20499/Website/Downloads/HouseStateFirstPrefsByPollingPlaceDownload-20499-NSW.csv', skip = 1) %>% 
  rbind(read_csv('https://results.aec.gov.au/20499/Website/Downloads/HouseStateFirstPrefsByPollingPlaceDownload-20499-VIC.csv', skip = 1)) %>% 
  rbind(read_csv('https://results.aec.gov.au/20499/Website/Downloads/HouseStateFirstPrefsByPollingPlaceDownload-20499-QLD.csv', skip = 1)) %>% 
  rbind(read_csv('https://results.aec.gov.au/20499/Website/Downloads/HouseStateFirstPrefsByPollingPlaceDownload-20499-SA.csv', skip = 1)) %>% 
  rbind(read_csv('https://results.aec.gov.au/20499/Website/Downloads/HouseStateFirstPrefsByPollingPlaceDownload-20499-WA.csv', skip = 1)) %>% 
  rbind(read_csv('https://results.aec.gov.au/20499/Website/Downloads/HouseStateFirstPrefsByPollingPlaceDownload-20499-TAS.csv', skip = 1)) %>% 
  rbind(read_csv('https://results.aec.gov.au/20499/Website/Downloads/HouseStateFirstPrefsByPollingPlaceDownload-20499-NT.csv', skip = 1)) %>% 
  rbind(read_csv('https://results.aec.gov.au/20499/Website/Downloads/HouseStateFirstPrefsByPollingPlaceDownload-20499-ACT.csv', skip = 1))
coalition_contest_2016 <- fp_booth_2016 %>% 
  group_by(DivisionNm, PartyNm, HistoricElected) %>% 
  summarise(OrdinaryVotes = sum(OrdinaryVotes)) %>%
  filter(PartyNm %in% c('Liberal', 'Country Liberals (NT)',
                        'Liberal National Party of Queensland',
                        'The Nationals')) %>% 
  group_by(DivisionNm) %>% 
  top_n(1) %>% 
  select(DivisionNm, PartyNm)
Selecting by OrdinaryVotes

If we look at a couple of the states where high income booths tend to vote strongly for the coalition as well as lower income booths, we can see that some (but not all) of the lower income booths are contested by The Nationals. This indicares (not surprisingly) that Nationals voters and Liberal voters are different socio-economically, or possibly that city and country coalition voters differ.

polling_place_2pp_clean %>% 
  mutate(DivisionNm = stringr::str_to_title(DivisionNm)) %>%
  inner_join(coalition_contest_2016) %>% 
  filter(StateAb == 'NSW') %>% 
  ggplot(aes(y = ALP_Percent/100, x = median_household_income, colour = PartyNm)) +
  geom_point(size = 3) +
  theme_classic(base_size = 16) + scale_color_manual(values = c('blue', 'dark green')) +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::dollar) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', x = 'Booth Median Income',
       y = 'ALP 2pp Percentage', colour = 'Coalition Party', 
       subtitle = 'by Polling Booth, Unweighted (NSW)') 

polling_place_2pp_clean %>% 
  mutate(DivisionNm = stringr::str_to_title(DivisionNm)) %>%
  inner_join(coalition_contest_2016) %>% 
  filter(StateAb == 'VIC') %>% 
  ggplot(aes(y = ALP_Percent/100, x = median_household_income, colour = PartyNm)) +
  geom_point(size = 3) +
  theme_classic(base_size = 16) + scale_color_manual(values = c('blue', 'dark green')) +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::dollar) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', x = 'Booth Median Income',
       y = 'ALP 2pp Percentage', colour = 'Coalition Party', 
       subtitle = 'by Polling Booth, Unweighted (VIC)') 

This effect is less clear in states where the Nationals aren’t as prominent, either because the Nationals aren’t as prominent (SA, WA, TAS), or are merged with the Liberals (QLD).

polling_place_2pp_clean %>% 
  mutate(DivisionNm = stringr::str_to_title(DivisionNm)) %>%
  inner_join(coalition_contest_2016) %>% 
  filter(StateAb == 'WA') %>% 
  ggplot(aes(y = ALP_Percent/100, x = median_household_income, colour = PartyNm)) +
  geom_point(size = 3) +
  theme_classic(base_size = 16) + scale_color_manual(values = c('blue', 'dark green')) +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::dollar) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', x = 'Booth Median Income',
       y = 'ALP 2pp Percentage', colour = 'Coalition Party', 
       subtitle = 'by Polling Booth, Unweighted (WA)') 

Perhaps we would be better off using the geographical classifications from the AEC.

library(rvest)

webpage <- read_html("http://results.aec.gov.au/20499/Website/HouseDivisionClassifications-20499-NAT.htm")

Division_Classifications <- webpage %>%
  html_nodes("#divisionClassifications") %>% 
  html_table(fill = TRUE) %>%
  .[[1]]
Division_Classifications <- Division_Classifications %>% 
  filter(Division != 'Total Enrolment')

The graph below shows that the booths that have a low ALP 2pp and a low median income are primarily rural booths. This relationship seems stronger than the Lib/Nat split.

polling_place_2pp_clean %>% 
  mutate(Division = stringr::str_to_title(DivisionNm)) %>%
  inner_join(Division_Classifications) %>% 
  filter(StateAb == 'NSW') %>% 
  ggplot(aes(y = ALP_Percent/100, x = median_household_income, colour = Demographic)) +
  geom_point(size = 1) +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::dollar) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', 
       y = 'ALP 2pp Percentage',
       x = 'Booth Median Income', colour = 'Region',
       subtitle = 'by Polling Booth, Unweighted (NSW)')

Looking at all states we see a similar relationship, although less strong than in NSW.

polling_place_2pp_clean %>% 
  mutate(Division = stringr::str_to_title(DivisionNm)) %>%
  inner_join(Division_Classifications) %>% 
  ggplot(aes(y = ALP_Percent/100, x = median_household_income, colour = Demographic)) +
  geom_point(size = 1) +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::dollar) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', y = 'ALP 2pp Percentage',
       x = 'Median Booth Income', colour = 'Region',
       subtitle = 'by Polling Booth, Unweighted')

What about some of the other variables?

polling_place_2pp_clean %>% 
  mutate(Division = stringr::str_to_title(DivisionNm)) %>%
  inner_join(Division_Classifications) %>% 
  ggplot(aes(y = ALP_Percent/100, x = average_household_size, colour = Demographic)) +
  geom_point(size = 1) +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', y = 'ALP 2pp Percentage',
       x = 'Average Household Size', colour = 'Region',
       subtitle = 'by Polling Booth, Unweighted')

polling_place_2pp_clean %>% 
  mutate(Division = stringr::str_to_title(DivisionNm)) %>%
  inner_join(Division_Classifications) %>% 
  ggplot(aes(y = ALP_Percent/100, x = percent_female, colour = Demographic)) +
  geom_point(size = 1) +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  theme(legend.position = 'bottom') +
  scale_x_continuous(labels=scales::percent) +
  scale_y_continuous(labels=scales::percent) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', y = 'ALP 2pp Percentage',
       x = 'Percent Female', colour = 'Region',
       subtitle = 'by Polling Booth, Unweighted')

polling_place_2pp_clean %>% 
  select(ALP_Percent, Swing, median_age, median_household_income, average_household_size,
         persons_per_bedroom, median_weekly_rent, median_annual_mortgage,
         percent_female, percent_defacto, percent_born_in_australia,
         percent_unit, percent_mortgage, percent_rent) %>% 
  cor %>% 
  kable()
ALP_Percent Swing median_age median_household_income average_household_size persons_per_bedroom median_weekly_rent median_annual_mortgage percent_female percent_defacto percent_born_in_australia percent_unit percent_mortgage percent_rent
ALP_Percent 1.0000000 -0.2924398 -0.4148188 0.0049899 0.1785014 0.3698085 0.1675435 0.1230552 0.1245266 0.1270139 -0.3301750 NA NA NA
Swing -0.2924398 1.0000000 0.0592447 0.1044271 -0.0872137 0.0165807 0.0817794 0.0964162 0.0734776 0.0042180 -0.0448560 NA NA NA
median_age -0.4148188 0.0592447 1.0000000 -0.4804955 -0.5175758 -0.5943939 -0.4116337 -0.4221270 -0.0574141 -0.0502159 0.5197535 NA NA NA
median_household_income 0.0049899 0.1044271 -0.4804955 1.0000000 0.4183950 0.3362658 0.8029106 0.8644605 0.1982974 -0.0693950 -0.3959055 NA NA NA
average_household_size 0.1785014 -0.0872137 -0.5175758 0.4183950 1.0000000 0.3887206 0.3408666 0.3284517 -0.0032833 -0.5164718 -0.3020229 NA NA NA
persons_per_bedroom 0.3698085 0.0165807 -0.5943939 0.3362658 0.3887206 1.0000000 0.4120754 0.4015767 0.0035249 0.0094906 -0.5938012 NA NA NA
median_weekly_rent 0.1675435 0.0817794 -0.4116337 0.8029106 0.3408666 0.4120754 1.0000000 0.9276979 0.4307971 -0.1337758 -0.6013994 NA NA NA
median_annual_mortgage 0.1230552 0.0964162 -0.4221270 0.8644605 0.3284517 0.4015767 0.9276979 1.0000000 0.3628219 -0.1183373 -0.5499270 NA NA NA
percent_female 0.1245266 0.0734776 -0.0574141 0.1982974 -0.0032833 0.0035249 0.4307971 0.3628219 1.0000000 -0.1010107 -0.1145354 NA NA NA
percent_defacto 0.1270139 0.0042180 -0.0502159 -0.0693950 -0.5164718 0.0094906 -0.1337758 -0.1183373 -0.1010107 1.0000000 0.2383005 NA NA NA
percent_born_in_australia -0.3301750 -0.0448560 0.5197535 -0.3959055 -0.3020229 -0.5938012 -0.6013994 -0.5499270 -0.1145354 0.2383005 1.0000000 NA NA NA
percent_unit NA NA NA NA NA NA NA NA NA NA NA 1 NA NA
percent_mortgage NA NA NA NA NA NA NA NA NA NA NA NA 1 NA
percent_rent NA NA NA NA NA NA NA NA NA NA NA NA NA 1
polling_place_2pp_clean %>% 
  mutate(Division = stringr::str_to_title(DivisionNm)) %>%
  inner_join(Division_Classifications) %>% 
  ggplot(aes(y = ALP_Percent/100, x = persons_per_bedroom, colour = Demographic)) +
  geom_point(size = 1) +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', y = 'ALP 2pp Percentage',
       x = 'Persons per Bedroom', colour = 'Region',
       subtitle = 'by Polling Booth, Unweighted')

polling_place_2pp_clean %>% 
  mutate(Division = stringr::str_to_title(DivisionNm)) %>%
  inner_join(Division_Classifications) %>% 
  ggplot(aes(y = ALP_Percent/100, x = percent_unit, colour = Demographic)) +
  geom_point(size = 1) +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::percent) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', y = 'ALP 2pp Percentage',
       x = 'Percent of Dwellings - Unit', colour = 'Region',
       subtitle = 'by Polling Booth, Unweighted')

polling_place_2pp_clean %>% 
  mutate(Division = stringr::str_to_title(DivisionNm)) %>%
  inner_join(Division_Classifications) %>% 
  ggplot(aes(y = ALP_Percent/100, x = percent_mortgage, colour = Demographic)) +
  geom_point(size = 1) +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::percent) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', y = 'ALP 2pp Percentage',
       x = 'Percent of Dwellings - Under Mortgage', colour = 'Region',
       subtitle = 'by Polling Booth, Unweighted')

polling_place_2pp_clean %>% 
  mutate(Division = stringr::str_to_title(DivisionNm)) %>%
  inner_join(Division_Classifications) %>% 
  ggplot(aes(y = ALP_Percent/100, x = percent_rent, colour = Demographic)) +
  geom_point(size = 1) +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::percent) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', y = 'ALP 2pp Percentage',
       x = 'Percent of Dwellings - Renting', colour = 'Region',
       subtitle = 'by Polling Booth, Unweighted')

polling_place_2pp_clean %>% 
  mutate(Division = stringr::str_to_title(DivisionNm)) %>%
  inner_join(Division_Classifications) %>% 
  ggplot(aes(y = ALP_Percent/100, x = percent_indig, colour = Demographic)) +
  geom_point(size = 1) +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::percent) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', y = 'ALP 2pp Percentage',
       x = 'Percent Indigeneous', colour = 'Region',
       subtitle = 'by Polling Booth, Unweighted')

polling_place_2pp_clean %>% 
  mutate(Division = stringr::str_to_title(DivisionNm)) %>%
  inner_join(Division_Classifications) %>% 
  ggplot(aes(y = ALP_Percent/100, x = percent_born_in_australia, colour = Demographic)) +
  geom_point(size = 1) +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::percent) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', y = 'ALP 2pp Percentage',
       x = 'Percent Born in Australia', colour = 'Region',
       subtitle = 'by Polling Booth, Unweighted')

polling_place_2pp_clean %>% 
  mutate(Division = stringr::str_to_title(DivisionNm)) %>%
  inner_join(Division_Classifications) %>% 
  ggplot(aes(y = ALP_Percent/100, x = percent_defacto, colour = Demographic)) +
  geom_point(size = 1) +
  theme_classic(base_size = 16) + scale_color_brewer(palette = "Dark2") +
  theme(legend.position = 'bottom') +
  scale_y_continuous(labels=scales::percent) +
  scale_x_continuous(labels=scales::percent) +
  labs(title = '2016 Election: ALP 2 Party Preferred Percentage', y = 'ALP 2pp Percentage',
       x = 'Percent in a Defacto Relationship', colour = 'Region',
       subtitle = 'by Polling Booth, Unweighted')

LS0tCnRpdGxlOiAiRXhwbG9yZSBDZW5zdXMyMDE2IFBhY2thZ2UiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCkl0IGxvb2tzIGxpa2UgUmF1c3RhdHMgbWlnaHQgbm90IGJlIHdoYXQgSSBhbSBsb29raW5nIGZvciB0byBnZXQgU0xBIGxldmVsIGNlbnN1cyBkYXRhIHF1aWNrbHkuIExldCdzIHRyeSBDZW5zdXMyMDE2IGZyb20gSHVnaCBQYXJzb25hZ2UuCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSwgZXJyb3I9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KENlbnN1czIwMTYpCmxpYnJhcnkoZWVjaGlkbmEpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoa2FibGVFeHRyYSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmc9RkFMU0UpCiMga25pdHI6Om9wdHNfY2h1bmskc2V0KGVycm9yPUZBTFNFKQprbml0cjo6b3B0c19jaHVuayRzZXQobWVzc2FnZT1GQUxTRSkKYGBgCgpgYGB7cn0KZnVsbF8yMDE2X2NlbnN1cyA8LSBDZW5zdXMyMDE2X3dpZGVfYnlfU0EyX3llYXIgJT4lIAogIGZpbHRlcih5ZWFyID09ICcyMDE2JyApCmhlYWQoZnVsbF8yMDE2X2NlbnN1cykKYGBgCgpZZXMgLSB0aGlzIGlzIHdoYXQgSSBuZWVkLgoKTG9hZGluZyBvdGhlciB0YWJsZXMKCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KYW5jZXN0b3JpZXNfMjAxNiA8LSBDZW5zdXMyMDE2X2FuY2VzdG9yaWVzICU+JSAKICBmaWx0ZXIoeWVhciA9PSAnMjAxNicgKQpjb3VudHJpZXNfb2ZfYmlydGhfMjAxNiA8LSBDZW5zdXMyMDE2X2NvdW50cmllc19vZl9iaXJ0aCAlPiUgCiAgZmlsdGVyKHllYXIgPT0gJzIwMTYnICkKbGFuZ3VhZ2VzXzIwMTYgPC0gQ2Vuc3VzMjAxNl9sYW5ndWFnZXMgJT4lIAogIGZpbHRlcih5ZWFyID09ICcyMDE2JyApCnJlbGlnaW9uc18yMDE2IDwtIENlbnN1czIwMTZfcmVsaWdpb25zICU+JSAKICBmaWx0ZXIoeWVhciA9PSAnMjAxNicgKQpgYGAKCiMgRmVhdHVyZSBFbmdpbmVlcmluZwoKRWFjaCBvZiB0aGUgZm91ciB2YXJpYWJsZXMgYW5jZXN0b3J5LCBjb3VudHJ5IG9mIGJpcnRoLCBsYW5ndWFnZXMgYW5kIHJlbGlnaW9ucyBhcmUgcXVpdGUgZ3JhbnVsYXIsIGFuZCBpdCBtYXkgbWFrZSBzZW5zZSB0byBsb29rIGF0IHRoZXNlIHZhcmlhYmxlcyBhdCBhIGxvd2VyIGxldmVsIG9mIGdyYW51bGFyaXR5LiAKCkFuY2VzdG9yeToKYGBge3IsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIGVycm9yPUYsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpkb3dubG9hZC5maWxlKCdodHRwczovL3d3dy5hYnMuZ292LmF1L0FVU1NUQVRTL3N1YnNjcmliZXIubnNmL2xvZz9vcGVuYWdlbnQmMTI0OTBkbzAwMDFfMjAxOTEyLnhscyYxMjQ5LjAmRGF0YSUyMEN1YmVzJjY3NEVGQzRDQTBBM0Q4RkRDQTI1ODREMzAwMTJCOTA1JjAmMjAxOSYxOC4xMi4yMDE5JkxhdGVzdCcsICcuL0RhdGEvYW5jZXN0cnlfY2xhc3NpZmljYXRpb24ueGxzJywgbWV0aG9kID0gJ2xpYmN1cmwnKQoKYW5jZXN0cnlfY2xhc3NpZmljYXRpb25fNGRpZyA8LSAKICByZWFkeGw6OnJlYWRfeGxzKCcuL0RhdGEvYW5jZXN0cnlfY2xhc3NpZmljYXRpb24ueGxzJywgc2hlZXQgPSAnVGFibGUgMS4zJywgCiAgICAgICAgICAgICAgICAgICBza2lwID0gNywgY29sX25hbWVzID0gYygnWDEnLCAnWDInLCAnQW5jZXN0b3J5X0NvZGVfNCcsICdBbmNlc3RvcnknKSkgJT4lIAogIGZpbHRlcighaXMubmEoQW5jZXN0b3J5KSkgJT4lIAogIHNlbGVjdChBbmNlc3RvcnlfQ29kZV80LCBBbmNlc3RvcnkpCgphbmNlc3RyeV9jbGFzc2lmaWNhdGlvbl8xZGlnIDwtIAogIHJlYWR4bDo6cmVhZF94bHMoJy4vRGF0YS9hbmNlc3RyeV9jbGFzc2lmaWNhdGlvbi54bHMnLCBzaGVldCA9ICdUYWJsZSAxLjEnLCAKICAgICAgICAgICAgICAgICAgIHNraXAgPSA1LCBjb2xfbmFtZXMgPSBjKCdBbmNlc3RvcnlfQ29kZV8xJywgJ0FuY2VzdG9yeV9Hcm91cCcpKSU+JSAKICBmaWx0ZXIoIWlzLm5hKEFuY2VzdG9yeV9Hcm91cCkpCmBgYAoKQ291bnRyeSBvZiBiaXJ0aApgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CmRvd25sb2FkLmZpbGUoJ2h0dHBzOi8vd3d3LmFicy5nb3YuYXUvYXVzc3RhdHMvc3Vic2NyaWJlci5uc2YvbG9nP29wZW5hZ2VudCZzYWNjXzEyNjkwZG8wMDAxXzIwMTkwMy54bHMmMTI2OS4wJkRhdGElMjBDdWJlcyY0ODBCRDczMEFGNDJENTE1Q0EyNTgzQkQwMDc3MDdDNSYwJjIwMTYmMTUuMDMuMjAxOSZMYXRlc3QnLCAnLi9EYXRhL2NvdW50cnlfY2xhc3NpZmljYXRpb24ueGxzJywgbWV0aG9kID0gJ2xpYmN1cmwnKQoKY291bnRyeV9jbGFzc2lmaWNhdGlvbl80ZGlnIDwtIAogIHJlYWR4bDo6cmVhZF94bHMoJy4vRGF0YS9jb3VudHJ5X2NsYXNzaWZpY2F0aW9uLnhscycsIHNoZWV0ID0gJ1RhYmxlIDEuMycsIAogICAgICAgICAgICAgICAgICAgc2tpcCA9IDcsIGNvbF9uYW1lcyA9IGMoJ1gxJywgJ1gyJywgJ0NvdW50cnlfQ29kZV80JywgJ0NvdW50cnknKSkgJT4lIAogIGZpbHRlcighaXMubmEoQ291bnRyeSkpICU+JSAKICBzZWxlY3QoLVgxLCAtWDIpCgpjb3VudHJ5X2NsYXNzaWZpY2F0aW9uXzJkaWcgPC0gCiAgcmVhZHhsOjpyZWFkX3hscygnLi9EYXRhL2NvdW50cnlfY2xhc3NpZmljYXRpb24ueGxzJywgc2hlZXQgPSAnVGFibGUgMS4yJywgCiAgICAgICAgICAgICAgICAgICBza2lwID0gNiwgY29sX25hbWVzID0gYygnWDEnLCAnQ291bnRyeV9Db2RlXzInLCAnQ291bnRyeV9OYW1lXzInKSkgJT4lIAogIGZpbHRlcighaXMubmEoQ291bnRyeV9OYW1lXzIpKSAlPiUgCiAgc2VsZWN0KC1YMSkKCmNvdW50cnlfY2xhc3NpZmljYXRpb25fMWRpZyA8LSAKICByZWFkeGw6OnJlYWRfeGxzKCcuL0RhdGEvY291bnRyeV9jbGFzc2lmaWNhdGlvbi54bHMnLCBzaGVldCA9ICdUYWJsZSAxLjEnLCAKICAgICAgICAgICAgICAgICAgIHNraXAgPSA1LCBjb2xfbmFtZXMgPSBjKCdDb3VudHJ5X0NvZGVfMScsICdDb3VudHJ5X0dyb3VwJykpICU+JSAKICBmaWx0ZXIoIWlzLm5hKENvdW50cnlfR3JvdXApKQpgYGAKCkxhbmd1YWdlCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KZG93bmxvYWQuZmlsZSgnaHR0cHM6Ly93d3cuYWJzLmdvdi5hdS9BVVNTVEFUUy9zdWJzY3JpYmVyLm5zZi9sb2c/b3BlbmFnZW50JkFTQ0xfMTI2NzBETzAwMDFfMjAxNzAzLnhscyYxMjY3LjAmRGF0YSUyMEN1YmVzJkY4NDYyMENGNkUxM0Y3RThDQTI1N0ZGMTAwMUU2OEE3JjAmMjAxNiYyOC4wMy4yMDE3JkxhdGVzdCcsICcuL0RhdGEvbGFuZ3VhZ2VfY2xhc3NpZmljYXRpb24ueGxzJywgbWV0aG9kID0gJ2xpYmN1cmwnKQoKbGFuZ3VhZ2VfY2xhc3NpZmljYXRpb25fNGRpZyA8LSAKICByZWFkeGw6OnJlYWRfeGxzKCcuL0RhdGEvbGFuZ3VhZ2VfY2xhc3NpZmljYXRpb24ueGxzJywgc2hlZXQgPSAnVGFibGUgMS4zJywgCiAgICAgICAgICAgICAgICAgICBza2lwID0gOCwgY29sX25hbWVzID0gYygnWDEnLCAnWDInLCAnWDMnLCAnWDQnLCAnTGFuZ3VhZ2VfQ29kZV8zJywgJ0xhbmd1YWdlJykpICU+JSAKICBmaWx0ZXIoIWlzLm5hKExhbmd1YWdlKSkgJT4lIAogIHNlbGVjdCgtWDEsIC1YMiwgLVgzLCAtWDQpCgpsYW5ndWFnZV9jbGFzc2lmaWNhdGlvbl8xZGlnIDwtIAogIHJlYWR4bDo6cmVhZF94bHMoJy4vRGF0YS9sYW5ndWFnZV9jbGFzc2lmaWNhdGlvbi54bHMnLCBzaGVldCA9ICdUYWJsZSAxLjEnLCAKICAgICAgICAgICAgICAgICAgIHNraXAgPSA1LCBjb2xfbmFtZXMgPSBjKCdMYW5ndWFnZV9Db2RlXzEnLCAnTGFuZ3VhZ2VfR3JvdXAnKSkgJT4lIAogIGZpbHRlcighaXMubmEoTGFuZ3VhZ2VfR3JvdXApKQpgYGAKClJlbGlnaW9uCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KZG93bmxvYWQuZmlsZSgnaHR0cHM6Ly93d3cuYWJzLmdvdi5hdS9BVVNTVEFUUy9zdWJzY3JpYmVyLm5zZi9sb2c/b3BlbmFnZW50JkFTQ1JHXzEyNjYwRE8wMDAxXzIwMTcwNy54bHMmMTI2Ni4wJkRhdGElMjBDdWJlcyZCM0VBRkUzRkU2MTgwRDM3Q0EyNTdGRjEwMDFFNjczQyYwJjIwMTYmMTQuMDcuMjAxNyZMYXRlc3QnLCAnLi9EYXRhL3JlbGlnaW9uX2NsYXNzaWZpY2F0aW9uLnhscycsIG1ldGhvZCA9ICdsaWJjdXJsJykKCnJlbGlnaW9uX2NsYXNzaWZpY2F0aW9uXzNkaWcgPC0gCiAgcmVhZHhsOjpyZWFkX3hscygnLi9EYXRhL3JlbGlnaW9uX2NsYXNzaWZpY2F0aW9uLnhscycsIHNoZWV0ID0gJ1RhYmxlIDEuMicsIAogICAgICAgICAgICAgICAgICAgc2tpcCA9IDYsIGNvbF9uYW1lcyA9IGMoJ1gxJywgJ1JlbGlnaW9uX0NvZGVfMycsICdSZWxpZ2lvbicpKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShSZWxpZ2lvbikpICU+JSAKICBzZWxlY3QoLVgxKQoKcmVsaWdpb25fY2xhc3NpZmljYXRpb25fMWRpZyA8LSAKICByZWFkeGw6OnJlYWRfeGxzKCcuL0RhdGEvcmVsaWdpb25fY2xhc3NpZmljYXRpb24ueGxzJywgc2hlZXQgPSAnVGFibGUgMS4xJywgCiAgICAgICAgICAgICAgICAgICBza2lwID0gNSwgY29sX25hbWVzID0gYygnUmVsaWdpb25fQ29kZV8xJywgJ1JlbGlnaW9uX0dyb3VwJykpICU+JSAKICBmaWx0ZXIoIWlzLm5hKFJlbGlnaW9uX0dyb3VwKSkKYGBgCgoKCgojIENvbWJpbmUgd2l0aCBlbGVjdGlvbiBkYXRhCgpBZ2dyZWdhdGUgYXQgdGhlIFNBMiBsZXZlbCAtIGFkZCB1bmxlc3MgdmFyaWFibGUgY29udGFpbnMgbWVkaWFuLCBhdmVyYWdlLCBwZXJzb25zX3Blcl9iZWRyb29tCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KY2Vuc3VzXzIwMTZfYWxsX3ZhcnMgPC0gQ2Vuc3VzMjAxNl93aWRlX2J5X1NBMl95ZWFyICU+JSAKICBmaWx0ZXIoeWVhciA9PSAnMjAxNicpICU+JSAKICByb3d3aXNlKCkgJT4lIAogIG11dGF0ZShzYTJfaWQgPSBwYXN0ZTAoc3Vic3RyKHNhMl9jb2RlLCAxLCAxKSwgc3Vic3RyKHNhMl9jb2RlLCA2LCA5KSkpICU+JSAKICBmaWx0ZXIoaXNNaXNzaW5nID09IEZBTFNFKSAlPiUgCiAgbXV0YXRlKHBlcmNlbnRfZmVtYWxlID0gZmVtYWxlL3BlcnNvbnMsCiAgICAgICAgIHBlcmNlbnRfZGVmYWN0byA9IGRlZmFjdG9fcGVyc29ucy9wZXJzb25zLAogICAgICAgICBwZXJjZW50X21hcnJpZWQgPSBtYXJyaWVkX3BlcnNvbnMvcGVyc29ucywKICAgICAgICAgcGVyY2VudF9pbmRpZyA9IGluZGlnX3BlcnNvbnMvcGVyc29ucywKICAgICAgICAgcGVyY2VudF9ib3JuX2luX2F1c3RyYWxpYSA9IGJvcm5faW5fYXVzdHJhbGlhL3BlcnNvbnMsCiAgICAgICAgIHBlcmNlbnRfdW5pdCA9IGZsYXRfb3JfdW5pdC9uX2R3ZWxsaW5ncywKICAgICAgICAgcGVyY2VudF9tb3J0Z2FnZSA9IGR3ZWxsaW5nX293bmVkX21vcnRnYWdlL25fZHdlbGxpbmdzLAogICAgICAgICBwZXJjZW50X3JlbnQgPSBkd2VsbGluZ19yZW50ZWQvbl9kd2VsbGluZ3MpCgoKY2Vuc3VzXzIwMTZfbWVhbnMgPC0gY2Vuc3VzXzIwMTZfYWxsX3ZhcnMgJT4lIAogIHNlbGVjdChtZWRpYW5fYWdlLCBtZWRpYW5faG91c2Vob2xkX2luY29tZSwgYXZlcmFnZV9ob3VzZWhvbGRfc2l6ZSwgCiAgICAgICAgIHBlcnNvbnNfcGVyX2JlZHJvb20sIG1lZGlhbl93ZWVrbHlfcmVudCwgbWVkaWFuX2FubnVhbF9tb3J0Z2FnZSwgc2EyX2lkKSAlPiUgCiAgZ3JvdXBfYnkoc2EyX2lkKSAlPiUgCiAgc3VtbWFyaXNlX2FsbChtZWFuLCBuYS5ybSA9IFRSVUUpCgpjZW5zdXNfMjAxNl9jb3VudHMgPC0gY2Vuc3VzXzIwMTZfYWxsX3ZhcnMgJT4lIAogIHNlbGVjdChuX2R3ZWxsaW5ncywgcGVyc29ucywgZmVtYWxlLCBtYWxlLCAKICAgICAgICAgbWFycmllZF9wZXJzb25zLCBtYXJyaWVkX2ZlbWFsZXMsIG1hcnJpZWRfbWFsZXMsIGRlZmFjdG9fcGVyc29ucywgCiAgICAgICAgIGRlZmFjdG9fZmVtYWxlcywgZGVmYWN0b19tYWxlcywgbm90bWFycmllZF9wZXJzb25zLCAKICAgICAgICAgbm90bWFycmllZF9mZW1hbGVzLCBub3RtYXJyaWVkX21hbGVzLCBpbmRpZ19wZXJzb25zLCAKICAgICAgICAgaW5kaWdfbWFsZXMsIGluZGlnX2ZlbWFsZXMsIG5vbl9pbmRpZ19wZXJzb25zLCAKICAgICAgICAgbm9uX2luZGlnX2ZlbWFsZXMsIG5vbl9pbmRpZ19tYWxlcywgbm90X3N0YXRlZF9pbmRpZ19wZXJzb25zLCAKICAgICAgICAgbm90X3N0YXRlZF9pbmRpZ19tYWxlcywgbm90X3N0YXRlZF9pbmRpZ19mZW1hbGVzLCAKICAgICAgICAgYm9ybl9pbl9hdXN0cmFsaWEsIGJvcm5fb3ZlcnNlYXMsIGNvdW50cnlfbm90X3N0YXRlZCwgCiAgICAgICAgIHNlcGFyYXRlX2hvdXNlLCBmbGF0X29yX3VuaXQsIGhvdXNpbmdfb3RoZXJfb3Jfbm90X3N0YXRlZCwgc2VtaV9vcl90b3duaG91c2UsIAogICAgICAgICBkd2VsbGluZ19vd25lZF9vdXRyaWdodCwgZHdlbGxpbmdfb3duZWRfbW9ydGdhZ2UsIGR3ZWxsaW5nX290aGVyX29yX25vdF9zdGF0ZWQsCiAgICAgICAgIGR3ZWxsaW5nX3JlbnRlZCwgc2EyX2lkKSAlPiUgCiAgZ3JvdXBfYnkoc2EyX2lkKSAlPiUgCiAgc3VtbWFyaXNlX2FsbChzdW0sIG5hLnJtID0gVFJVRSkgJT4lIAogIG11dGF0ZShwZXJjZW50X2ZlbWFsZSA9IGZlbWFsZS9wZXJzb25zLAogICAgICAgICBwZXJjZW50X2RlZmFjdG8gPSBkZWZhY3RvX3BlcnNvbnMvcGVyc29ucywKICAgICAgICAgcGVyY2VudF9tYXJyaWVkID0gbWFycmllZF9wZXJzb25zL3BlcnNvbnMsCiAgICAgICAgIHBlcmNlbnRfaW5kaWcgPSBpbmRpZ19wZXJzb25zL3BlcnNvbnMsCiAgICAgICAgIHBlcmNlbnRfYm9ybl9pbl9hdXN0cmFsaWEgPSBib3JuX2luX2F1c3RyYWxpYS9wZXJzb25zLAogICAgICAgICBwZXJjZW50X3VuaXQgPSBmbGF0X29yX3VuaXQvbl9kd2VsbGluZ3MsCiAgICAgICAgIHBlcmNlbnRfbW9ydGdhZ2UgPSBkd2VsbGluZ19vd25lZF9tb3J0Z2FnZS9uX2R3ZWxsaW5ncywKICAgICAgICAgcGVyY2VudF9yZW50ID0gZHdlbGxpbmdfcmVudGVkL25fZHdlbGxpbmdzKQpgYGAKCgpTbyB3aGF0IEkgbmVlZCBpcyB3ZWlnaHRlZCBkZW1vZ3JhcGhpYyBkYXRhIGZvciBlYWNoIG9mIHRoZSBwb2xsaW5nIHBsYWNlcyBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIHBlb3BsZSBmcm9tIGVhY2ggU0xBMiB3aG8gdm90ZWQgYXQgdGhlIHBvbGxpbmcgcGxhY2UuIFNpbmNlIHdlIGRvbid0IGtub3cgd2hvIHZvdGVkIHdoZXJlLCBhbmQgd2hvIGNhbiB2b3RlIGF0IGFsbCwgd2UgYXJlIG1ha2luZyB0aGUgbmFpdmUgYXNzdW1wdGlvbnMgdGhhdCAKKiBWb3RlcnMgYXQgZWFjaCBTTEEgYXJlIHNpbWlsYXIKKiBWb3RlcnMgYXJlIHJlcHJlc2VudGl0aXZlIG9mIGNlbnN1cyByZXNwb25kZW50cyBhdCB0aGUgU0xBMiBsZXZlbC4KCkRvd25sb2FkIGFuZCBsb2FkIHBvbGxpbmcgcGxhY2VzIGJ5IFNBMQpgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9Cgpkb3dubG9hZC5maWxlKCdodHRwczovL3d3dy5hZWMuZ292LmF1L0VsZWN0aW9ucy9GZWRlcmFsX0VsZWN0aW9ucy8yMDE2L2ZpbGVzL3BvbGxpbmctcGxhY2UtYnktc2Excy0yMDE2Lnhsc3gnLCAnLi9EYXRhL3BvbGxpbmctcGxhY2UtYnktc2Excy0yMDE2Lnhsc3gnLCBtZXRob2QgPSAnbGliY3VybCcpCgpwb2xsaW5nX3BsYWNlX2RhdGEgPC0gcmVhZHhsOjpyZWFkX3hsc3goJy4vRGF0YS9wb2xsaW5nLXBsYWNlLWJ5LXNhMXMtMjAxNi54bHN4JykKYGBgCgoKQWdncmVnYXRlIHBvbGxpbmcgcGxhY2UgZGF0YSB0byBTQTIKCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KcG9sbGluZ19wbGFjZV9zYTIgPC0gcG9sbGluZ19wbGFjZV9kYXRhICU+JSAKICBtdXRhdGUoc2EyX2lkID0gZmxvb3IoU0ExX2lkIC8gMTAwKSkgJT4lIAogIGdyb3VwX2J5KHllYXIsIHN0YXRlX2FiLCBkaXZfbm0sIHBwX2lkLCBwcF9ubSwgc2EyX2lkKSAlPiUgCiAgc3VtbWFyaXNlKHZvdGVzID0gc3VtKHZvdGVzKSkKCmBgYAoKQ29tYmluZSB3aXRoIGRlbW9ncmFwaGljIGRhdGEgYW5kIGFnZ3JlZ2F0ZQoKYGBge3IsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIGVycm9yPUYsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpwb2xsaW5nX3BsYWNlX2RlbW9nIDwtIHBvbGxpbmdfcGxhY2Vfc2EyICU+JSAKICBtdXRhdGUoc2EyX2lkID0gYXMuY2hhcmFjdGVyKHNhMl9pZCkpICU+JSAKICBpbm5lcl9qb2luKGNlbnN1c18yMDE2X2FsbF92YXJzKQoKcG9sbGluZ19wbGFjZV9kZW1vZ19tZWFucyA8LSBwb2xsaW5nX3BsYWNlX2RlbW9nICU+JSAKICBzZWxlY3QoeWVhciwgc3RhdGVfYWIsIGRpdl9ubSwgcHBfaWQsIHBwX25tLCBzYTJfaWQsIHZvdGVzLAogICAgICAgICBtZWRpYW5fYWdlLCBtZWRpYW5faG91c2Vob2xkX2luY29tZSwgYXZlcmFnZV9ob3VzZWhvbGRfc2l6ZSwgCiAgICAgICAgIHBlcnNvbnNfcGVyX2JlZHJvb20sIG1lZGlhbl93ZWVrbHlfcmVudCwgbWVkaWFuX2FubnVhbF9tb3J0Z2FnZSwKICAgICAgICAgcGVyY2VudF9mZW1hbGUsIHBlcmNlbnRfZGVmYWN0bywgcGVyY2VudF9tYXJyaWVkLCBwZXJjZW50X2luZGlnLCAKICAgICAgICAgcGVyY2VudF9ib3JuX2luX2F1c3RyYWxpYSwgcGVyY2VudF91bml0LCBwZXJjZW50X21vcnRnYWdlLCBwZXJjZW50X3JlbnQpICU+JSAKICBncm91cF9ieSh5ZWFyLCBzdGF0ZV9hYiwgZGl2X25tLCBwcF9pZCwgcHBfbm0pICU+JSAKICBzdW1tYXJpc2VfYXQodmFycyhtZWRpYW5fYWdlLCBtZWRpYW5faG91c2Vob2xkX2luY29tZSwgCiAgICAgICAgICAgICAgICAgICAgYXZlcmFnZV9ob3VzZWhvbGRfc2l6ZSwgcGVyc29uc19wZXJfYmVkcm9vbSwgbWVkaWFuX3dlZWtseV9yZW50LCAKICAgICAgICAgICAgICAgICAgICBtZWRpYW5fYW5udWFsX21vcnRnYWdlLCBwZXJjZW50X2ZlbWFsZSwgcGVyY2VudF9kZWZhY3RvLCAKICAgICAgICAgICAgICAgICAgICBwZXJjZW50X21hcnJpZWQsIHBlcmNlbnRfaW5kaWcsIHBlcmNlbnRfYm9ybl9pbl9hdXN0cmFsaWEsCiAgICAgICAgICAgICAgICAgICAgcGVyY2VudF91bml0LCBwZXJjZW50X21vcnRnYWdlLCAKICAgICAgICAgICAgICAgICAgICBwZXJjZW50X3JlbnQpLCBmdW5zKHdlaWdodGVkLm1lYW4oLiwgdz12b3RlcykpKQpgYGAKQWRkIGluIDJwcCBhdCB0aGUgcG9sbGluZyBib290aCBsZXZlbApgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CmVsZWN0aW9uXzJwcCA8LSB0d29wYXJ0eV9wb2xsaW5nYm9vdGhfZG93bmxvYWQoKSAKCmBgYApgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CnBvbGxpbmdfcGxhY2VfMnBwIDwtIHBvbGxpbmdfcGxhY2VfZGVtb2dfbWVhbnMgJT4lIAogIGdyb3VwX2J5KCkgJT4lIAogIHJlbmFtZShTdGF0ZUFiID0gc3RhdGVfYWIsCiAgICAgICAgIERpdmlzaW9uTm0gPSBkaXZfbm0sCiAgICAgICAgIFBvbGxpbmdQbGFjZSA9IHBwX25tLAogICAgICAgICBQb2xsaW5nUGxhY2VJRCA9IHBwX2lkKSAlPiUgCiAgbXV0YXRlKERpdmlzaW9uTm0gPSB0b3VwcGVyKERpdmlzaW9uTm0pLAogICAgICAgICBQb2xsaW5nUGxhY2UgPSB0b3VwcGVyKFBvbGxpbmdQbGFjZSkpICU+JSAKICBsZWZ0X2pvaW4oZWxlY3Rpb25fMnBwICU+JSAKICAgICAgICAgICAgICBmaWx0ZXIoeWVhciA9PSAyMDE2KSkKYGBgCgpDaGVjayBmb3IgbWlzc2luZyBkYXRhCgpgYGB7cn0KcG9sbGluZ19wbGFjZV8ycHAgJT4lIAogIHN1bW1hcmlzZV9hbGwoZnVucyhzdW0oaXMubmEoLikpKSkKYGBgCldoaWNoIGJvb3RocyBhcmUgbnVsbD8KCmBgYHtyfQpwb2xsaW5nX3BsYWNlXzJwcCAlPiUgCiAgZmlsdGVyKGlzLm5hKFRvdGFsVm90ZXMpKSAlPiUgCiAgdGFieWwoUG9sbGluZ1BsYWNlKQpgYGAKClNvIHRoZSBBYnNlbnQsIFBvc3RhbHMsIFByZS1Qb2xsIGFuZCBQcm92aXNpb25hbCB2b3RlcyBhcmVuJ3QgaW4gdGhpcyB0YWJsZS4gTGV0J3MgY29tZSBiYWNrIHRvIHRob3NlLi4uIAoKYGBge3J9CnBvbGxpbmdfcGxhY2VfMnBwICU+JSAKICBzdW1tYXJpc2VfYWxsKGZ1bnMoc3VtKGlzLm51bGwoLikpKSkKYGBgCgpSZW1vdmUgdGhlIHJvd3Mgd2l0aCBOQXMKCmBgYHtyfQpwb2xsaW5nX3BsYWNlXzJwcF9jbGVhbiA8LSBwb2xsaW5nX3BsYWNlXzJwcCAlPiUgCiAgZmlsdGVyKCFpcy5uYShUb3RhbFZvdGVzKSkKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CnBvbGxpbmdfcGxhY2VfMnBwX2NsZWFuICU+JSAKICBzdW1tYXJpc2VfYWxsKGZ1bnMoc3VtKGlzLm5hKC4pKSkpCmBgYAoKV2hpY2ggcG9sbGluZyBzdGF0aW9ucyBoYXZlIG1pc3NpbmcgZGF0YT8gTm90IHRvbyBjb25jZXJuZWQgYWJvdXQgcG9zdCBjb2RlLCBhcyB0aGVyZSBhcmUgc29tZSBzcGVjaWFsIGJvb3RocwoKYGBge3IsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIGVycm9yPUYsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpwb2xsaW5nX3BsYWNlXzJwcF9jbGVhbiAlPiUgCiAgZmlsdGVyKGlzLm5hKG1lZGlhbl9hZ2UpfGlzLm5hKExhdGl0dWRlKSkKYGBgCkxvb2tzIGxpa2UgbW9iaWxlIHRlYW1zIGFuZCBwcmVwb2xsIGNlbnRyZXMsIGFuZCBvbmx5IGxhdGl0dWRlIGFuZCBsb25naXR1ZGUuIFdpbGwgcmVtb3ZlIHRoZSBCcmFuZCBtb2JpbGUgdGVhbSwgYXMgdGhlIGRlbW9ncmFwaGljIGRhdGEgZG9lcyBub3QgbG9vayB2YWxpZC4KCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KcG9sbGluZ19wbGFjZV8ycHBfY2xlYW48LSBwb2xsaW5nX3BsYWNlXzJwcF9jbGVhbiAlPiUgCiAgZHBseXI6OmZpbHRlcihQb2xsaW5nUGxhY2VJRCAhPSA2NTE2MSkKYGBgCgoKCiMgVmlzdWFsaXNpbmcgQmFzaWMgU3RhdGlzdGljcwpgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CnBvbGxpbmdfcGxhY2VfMnBwX2NsZWFuICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBMTlBfUGVyY2VudC8xMDApKSArIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIiwgY29sb3VyID0gJ2JsdWUnKSArCiAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxNikgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgbGFicyh0aXRsZSA9ICcyMDE2IEVsZWN0aW9uOiBMTlAgMiBQYXJ0eSBQcmVmZXJyZWQgUGVyY2VudGFnZScsIHggPSAnMlBQIFBlcmNlbnRhZ2UnLCAKICAgICAgIHkgPSAnRGVuc2l0eScsIHN1YnRpdGxlID0gJ2J5IFBvbGxpbmcgQm9vdGgsIFVud2VpZ2h0ZWQnKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KcG9sbGluZ19wbGFjZV8ycHBfY2xlYW4gJT4lIAogIGdncGxvdChhZXMoeCA9IEFMUF9QZXJjZW50LzEwMCkpICsgc3RhdF9kZW5zaXR5KGdlb209ImxpbmUiLCBjb2xvdXIgPSAncmVkJykgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTYpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIGxhYnModGl0bGUgPSAnMjAxNiBFbGVjdGlvbjogQUxQIDIgUGFydHkgUHJlZmVycmVkIFBlcmNlbnRhZ2UnLCB4ID0gJzJQUCBQZXJjZW50YWdlJywgCiAgICAgICB5ID0gJ0RlbnNpdHknLCBzdWJ0aXRsZSA9ICdieSBQb2xsaW5nIEJvb3RoLCBVbndlaWdodGVkJykKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CnBvbGxpbmdfcGxhY2VfMnBwX2NsZWFuICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBTd2luZy8xMDApKSArIHN0YXRfZGVuc2l0eShnZW9tPSJsaW5lIiwgY29sb3VyID0gJ3B1cnBsZScpICsKICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDE2KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsKICBsYWJzKHRpdGxlID0gJzIwMTYgRWxlY3Rpb246IFN3aW5nIHRvIEluY3VtYmVudCcsIHggPSAnU3dpbmcnLCAKICAgICAgIHkgPSAnRGVuc2l0eScsIHN1YnRpdGxlID0gJ2J5IFBvbGxpbmcgQm9vdGgsIFVud2VpZ2h0ZWQnKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KcG9sbGluZ19wbGFjZV8ycHBfY2xlYW4gJT4lIAogIGdncGxvdChhZXMoeCA9IG1lZGlhbl9ob3VzZWhvbGRfaW5jb21lKSkgKyBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIsIGNvbG91ciA9ICdwdXJwbGUnKSArCiAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxNikgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpkb2xsYXIpICsKICBsYWJzKHRpdGxlID0gJzIwMTYgQ2Vuc3VzOiBNZWRpYW4gSW5jb21lJywgeCA9ICdNZWRpYW4gSW5jb21lJywgCiAgICAgICB5ID0gJ0RlbnNpdHknLCBzdWJ0aXRsZSA9ICdieSBQb2xsaW5nIEJvb3RoLCBVbndlaWdodGVkJykKYGBgCgojIyBTdGF0ZSBCcmVha2Rvd25zCgpDYW4gd2UgbG9vayBhdCB0aGVzZSBkaXN0cmlidXRpb25zIGJ5IHN0YXRlPwoKYGBge3IsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIGVycm9yPUYsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpwb2xsaW5nX3BsYWNlXzJwcF9jbGVhbiAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gQUxQX1BlcmNlbnQvMTAwLCBjb2xvdXIgPSBTdGF0ZUFiKSkgKyAKICBzdGF0X2RlbnNpdHkoZ2VvbT0ibGluZSIsIHBvc2l0aW9uID0gJ2RvZGdlJykgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTYpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsKICBsYWJzKHRpdGxlID0gJzIwMTYgRWxlY3Rpb246IEFMUCAyIFBhcnR5IFByZWZlcnJlZCBQZXJjZW50YWdlJywgeCA9ICcyUFAgUGVyY2VudGFnZScsIAogICAgICAgeSA9ICdGcmVxdWVuY3knLCBzdWJ0aXRsZSA9ICdieSBQb2xsaW5nIEJvb3RoLCBVbndlaWdodGVkJykKYGBgCgpXaGF0IGFib3V0IGJ5IG1lZGlhbiBpbmNvbWUKCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KcG9sbGluZ19wbGFjZV8ycHBfY2xlYW4gJT4lCiAgZ2dwbG90KGFlcyh5ID0gQUxQX1BlcmNlbnQvMTAwLCB4ID0gbWVkaWFuX2hvdXNlaG9sZF9pbmNvbWUsIGNvbG91ciA9IFN0YXRlQWIpKSArCiAgZ2VvbV9wb2ludCgpICsKICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDE2KSArIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OmRvbGxhcikgKwogIGxhYnModGl0bGUgPSAnMjAxNiBFbGVjdGlvbjogQUxQIDIgUGFydHkgUHJlZmVycmVkIFBlcmNlbnRhZ2UnLCB4ID0gJ0Jvb3RoIE1lZGlhbiBJbmNvbWUnLAogICAgICAgeSA9ICdBTFAgMnBwIFBlcmNlbnRhZ2UnLCBzdWJ0aXRsZSA9ICdieSBQb2xsaW5nIEJvb3RoLCBVbndlaWdodGVkJykgKwogIGZhY2V0X3dyYXAoflN0YXRlQWIsIG5yb3cgPSA0KQpgYGAKCldoYXQgYWJvdXQgY29tcGFyaW5nIE5TVyBlbGVjdG9yYXRlcz8gVGhlcmUgc2VlbXMgdG8gYmUgYW4gb2RkIHNlcGFyYXRpb24gaW4gaW5jb21lIGJhbmRzIGZvciBsb3cgQUxQIDJwcC4gQ291bGQgdGhpcyBiZSBhIHJlZ2lvbmFsIHZzIGNpdHkgZGlmZmVyZW5jZT8gCgpgYGB7ciwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CmZwX2Jvb3RoXzE2IDwtIGZpcnN0cHJlZl9wb2xsaW5nYm9vdGhfZG93bmxvYWQoKSAlPiUgCiAgZmlsdGVyKHllYXIgPT0gMjAxNikKYGBgCgoKYGBge3IsIGVycm9yPUYsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpwb2xsaW5nXzJjcCA8LSByZWFkX2NzdignaHR0cHM6Ly9yZXN1bHRzLmFlYy5nb3YuYXUvMjA0OTkvV2Vic2l0ZS9Eb3dubG9hZHMvSG91c2VUY3BCeUNhbmRpZGF0ZUJ5UG9sbGluZ1BsYWNlRG93bmxvYWQtMjA0OTkuY3N2Jywgc2tpcCA9IDEpCgpwb2xsaW5nXzJwcCA8LSByZWFkX2NzdignaHR0cHM6Ly9yZXN1bHRzLmFlYy5nb3YuYXUvMjA0OTkvV2Vic2l0ZS9Eb3dubG9hZHMvSG91c2VUcHBCeVBvbGxpbmdQbGFjZURvd25sb2FkLTIwNDk5LmNzdicsIHNraXAgPSAxKQoKZnBfYm9vdGhfMjAxNiA8LSByZWFkX2NzdignaHR0cHM6Ly9yZXN1bHRzLmFlYy5nb3YuYXUvMjA0OTkvV2Vic2l0ZS9Eb3dubG9hZHMvSG91c2VTdGF0ZUZpcnN0UHJlZnNCeVBvbGxpbmdQbGFjZURvd25sb2FkLTIwNDk5LU5TVy5jc3YnLCBza2lwID0gMSkgJT4lIAogIHJiaW5kKHJlYWRfY3N2KCdodHRwczovL3Jlc3VsdHMuYWVjLmdvdi5hdS8yMDQ5OS9XZWJzaXRlL0Rvd25sb2Fkcy9Ib3VzZVN0YXRlRmlyc3RQcmVmc0J5UG9sbGluZ1BsYWNlRG93bmxvYWQtMjA0OTktVklDLmNzdicsIHNraXAgPSAxKSkgJT4lIAogIHJiaW5kKHJlYWRfY3N2KCdodHRwczovL3Jlc3VsdHMuYWVjLmdvdi5hdS8yMDQ5OS9XZWJzaXRlL0Rvd25sb2Fkcy9Ib3VzZVN0YXRlRmlyc3RQcmVmc0J5UG9sbGluZ1BsYWNlRG93bmxvYWQtMjA0OTktUUxELmNzdicsIHNraXAgPSAxKSkgJT4lIAogIHJiaW5kKHJlYWRfY3N2KCdodHRwczovL3Jlc3VsdHMuYWVjLmdvdi5hdS8yMDQ5OS9XZWJzaXRlL0Rvd25sb2Fkcy9Ib3VzZVN0YXRlRmlyc3RQcmVmc0J5UG9sbGluZ1BsYWNlRG93bmxvYWQtMjA0OTktU0EuY3N2Jywgc2tpcCA9IDEpKSAlPiUgCiAgcmJpbmQocmVhZF9jc3YoJ2h0dHBzOi8vcmVzdWx0cy5hZWMuZ292LmF1LzIwNDk5L1dlYnNpdGUvRG93bmxvYWRzL0hvdXNlU3RhdGVGaXJzdFByZWZzQnlQb2xsaW5nUGxhY2VEb3dubG9hZC0yMDQ5OS1XQS5jc3YnLCBza2lwID0gMSkpICU+JSAKICByYmluZChyZWFkX2NzdignaHR0cHM6Ly9yZXN1bHRzLmFlYy5nb3YuYXUvMjA0OTkvV2Vic2l0ZS9Eb3dubG9hZHMvSG91c2VTdGF0ZUZpcnN0UHJlZnNCeVBvbGxpbmdQbGFjZURvd25sb2FkLTIwNDk5LVRBUy5jc3YnLCBza2lwID0gMSkpICU+JSAKICByYmluZChyZWFkX2NzdignaHR0cHM6Ly9yZXN1bHRzLmFlYy5nb3YuYXUvMjA0OTkvV2Vic2l0ZS9Eb3dubG9hZHMvSG91c2VTdGF0ZUZpcnN0UHJlZnNCeVBvbGxpbmdQbGFjZURvd25sb2FkLTIwNDk5LU5ULmNzdicsIHNraXAgPSAxKSkgJT4lIAogIHJiaW5kKHJlYWRfY3N2KCdodHRwczovL3Jlc3VsdHMuYWVjLmdvdi5hdS8yMDQ5OS9XZWJzaXRlL0Rvd25sb2Fkcy9Ib3VzZVN0YXRlRmlyc3RQcmVmc0J5UG9sbGluZ1BsYWNlRG93bmxvYWQtMjA0OTktQUNULmNzdicsIHNraXAgPSAxKSkKYGBgCgpgYGB7cn0KY29hbGl0aW9uX2NvbnRlc3RfMjAxNiA8LSBmcF9ib290aF8yMDE2ICU+JSAKICBncm91cF9ieShEaXZpc2lvbk5tLCBQYXJ0eU5tLCBIaXN0b3JpY0VsZWN0ZWQpICU+JSAKICBzdW1tYXJpc2UoT3JkaW5hcnlWb3RlcyA9IHN1bShPcmRpbmFyeVZvdGVzKSkgJT4lCiAgZmlsdGVyKFBhcnR5Tm0gJWluJSBjKCdMaWJlcmFsJywgJ0NvdW50cnkgTGliZXJhbHMgKE5UKScsCiAgICAgICAgICAgICAgICAgICAgICAgICdMaWJlcmFsIE5hdGlvbmFsIFBhcnR5IG9mIFF1ZWVuc2xhbmQnLAogICAgICAgICAgICAgICAgICAgICAgICAnVGhlIE5hdGlvbmFscycpKSAlPiUgCiAgZ3JvdXBfYnkoRGl2aXNpb25ObSkgJT4lIAogIHRvcF9uKDEpICU+JSAKICBzZWxlY3QoRGl2aXNpb25ObSwgUGFydHlObSkKYGBgCgpJZiB3ZSBsb29rIGF0IGEgY291cGxlIG9mIHRoZSBzdGF0ZXMgd2hlcmUgaGlnaCBpbmNvbWUgYm9vdGhzIHRlbmQgdG8gdm90ZSBzdHJvbmdseSBmb3IgdGhlIGNvYWxpdGlvbiBhcyB3ZWxsIGFzIGxvd2VyIGluY29tZSBib290aHMsIHdlIGNhbiBzZWUgdGhhdCBzb21lIChidXQgbm90IGFsbCkgb2YgdGhlIGxvd2VyIGluY29tZSBib290aHMgYXJlIGNvbnRlc3RlZCBieSBUaGUgTmF0aW9uYWxzLiBUaGlzIGluZGljYXJlcyAobm90IHN1cnByaXNpbmdseSkgdGhhdCBOYXRpb25hbHMgdm90ZXJzIGFuZCBMaWJlcmFsIHZvdGVycyBhcmUgZGlmZmVyZW50IHNvY2lvLWVjb25vbWljYWxseSwgb3IgcG9zc2libHkgdGhhdCBjaXR5IGFuZCBjb3VudHJ5IGNvYWxpdGlvbiB2b3RlcnMgZGlmZmVyLiAKYGBge3IsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIGVycm9yPUYsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpwb2xsaW5nX3BsYWNlXzJwcF9jbGVhbiAlPiUgCiAgbXV0YXRlKERpdmlzaW9uTm0gPSBzdHJpbmdyOjpzdHJfdG9fdGl0bGUoRGl2aXNpb25ObSkpICU+JQogIGlubmVyX2pvaW4oY29hbGl0aW9uX2NvbnRlc3RfMjAxNikgJT4lIAogIGZpbHRlcihTdGF0ZUFiID09ICdOU1cnKSAlPiUgCiAgZ2dwbG90KGFlcyh5ID0gQUxQX1BlcmNlbnQvMTAwLCB4ID0gbWVkaWFuX2hvdXNlaG9sZF9pbmNvbWUsIGNvbG91ciA9IFBhcnR5Tm0pKSArCiAgZ2VvbV9wb2ludChzaXplID0gMykgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTYpICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoJ2JsdWUnLCAnZGFyayBncmVlbicpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpkb2xsYXIpICsKICBsYWJzKHRpdGxlID0gJzIwMTYgRWxlY3Rpb246IEFMUCAyIFBhcnR5IFByZWZlcnJlZCBQZXJjZW50YWdlJywgeCA9ICdCb290aCBNZWRpYW4gSW5jb21lJywKICAgICAgIHkgPSAnQUxQIDJwcCBQZXJjZW50YWdlJywgY29sb3VyID0gJ0NvYWxpdGlvbiBQYXJ0eScsIAogICAgICAgc3VidGl0bGUgPSAnYnkgUG9sbGluZyBCb290aCwgVW53ZWlnaHRlZCAoTlNXKScpIApgYGAKCgpgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CnBvbGxpbmdfcGxhY2VfMnBwX2NsZWFuICU+JSAKICBtdXRhdGUoRGl2aXNpb25ObSA9IHN0cmluZ3I6OnN0cl90b190aXRsZShEaXZpc2lvbk5tKSkgJT4lCiAgaW5uZXJfam9pbihjb2FsaXRpb25fY29udGVzdF8yMDE2KSAlPiUgCiAgZmlsdGVyKFN0YXRlQWIgPT0gJ1ZJQycpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBBTFBfUGVyY2VudC8xMDAsIHggPSBtZWRpYW5faG91c2Vob2xkX2luY29tZSwgY29sb3VyID0gUGFydHlObSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAzKSArCiAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxNikgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygnYmx1ZScsICdkYXJrIGdyZWVuJykpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnYm90dG9tJykgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OmRvbGxhcikgKwogIGxhYnModGl0bGUgPSAnMjAxNiBFbGVjdGlvbjogQUxQIDIgUGFydHkgUHJlZmVycmVkIFBlcmNlbnRhZ2UnLCB4ID0gJ0Jvb3RoIE1lZGlhbiBJbmNvbWUnLAogICAgICAgeSA9ICdBTFAgMnBwIFBlcmNlbnRhZ2UnLCBjb2xvdXIgPSAnQ29hbGl0aW9uIFBhcnR5JywgCiAgICAgICBzdWJ0aXRsZSA9ICdieSBQb2xsaW5nIEJvb3RoLCBVbndlaWdodGVkIChWSUMpJykgCmBgYAoKVGhpcyBlZmZlY3QgaXMgbGVzcyBjbGVhciBpbiBzdGF0ZXMgd2hlcmUgdGhlIE5hdGlvbmFscyBhcmVuJ3QgYXMgcHJvbWluZW50LCBlaXRoZXIgYmVjYXVzZSB0aGUgTmF0aW9uYWxzIGFyZW4ndCBhcyBwcm9taW5lbnQgKFNBLCBXQSwgVEFTKSwgb3IgYXJlIG1lcmdlZCB3aXRoIHRoZSBMaWJlcmFscyAoUUxEKS4gIApgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CnBvbGxpbmdfcGxhY2VfMnBwX2NsZWFuICU+JSAKICBtdXRhdGUoRGl2aXNpb25ObSA9IHN0cmluZ3I6OnN0cl90b190aXRsZShEaXZpc2lvbk5tKSkgJT4lCiAgaW5uZXJfam9pbihjb2FsaXRpb25fY29udGVzdF8yMDE2KSAlPiUgCiAgZmlsdGVyKFN0YXRlQWIgPT0gJ1dBJykgJT4lIAogIGdncGxvdChhZXMoeSA9IEFMUF9QZXJjZW50LzEwMCwgeCA9IG1lZGlhbl9ob3VzZWhvbGRfaW5jb21lLCBjb2xvdXIgPSBQYXJ0eU5tKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsKICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDE2KSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCdibHVlJywgJ2RhcmsgZ3JlZW4nKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6ZG9sbGFyKSArCiAgbGFicyh0aXRsZSA9ICcyMDE2IEVsZWN0aW9uOiBBTFAgMiBQYXJ0eSBQcmVmZXJyZWQgUGVyY2VudGFnZScsIHggPSAnQm9vdGggTWVkaWFuIEluY29tZScsCiAgICAgICB5ID0gJ0FMUCAycHAgUGVyY2VudGFnZScsIGNvbG91ciA9ICdDb2FsaXRpb24gUGFydHknLCAKICAgICAgIHN1YnRpdGxlID0gJ2J5IFBvbGxpbmcgQm9vdGgsIFVud2VpZ2h0ZWQgKFdBKScpIApgYGAKCgpQZXJoYXBzIHdlIHdvdWxkIGJlIGJldHRlciBvZmYgdXNpbmcgdGhlIGdlb2dyYXBoaWNhbCBjbGFzc2lmaWNhdGlvbnMgZnJvbSB0aGUgQUVDLgoKYGBge3J9CmxpYnJhcnkocnZlc3QpCgp3ZWJwYWdlIDwtIHJlYWRfaHRtbCgiaHR0cDovL3Jlc3VsdHMuYWVjLmdvdi5hdS8yMDQ5OS9XZWJzaXRlL0hvdXNlRGl2aXNpb25DbGFzc2lmaWNhdGlvbnMtMjA0OTktTkFULmh0bSIpCgpEaXZpc2lvbl9DbGFzc2lmaWNhdGlvbnMgPC0gd2VicGFnZSAlPiUKICBodG1sX25vZGVzKCIjZGl2aXNpb25DbGFzc2lmaWNhdGlvbnMiKSAlPiUgCiAgaHRtbF90YWJsZShmaWxsID0gVFJVRSkgJT4lCiAgLltbMV1dCkRpdmlzaW9uX0NsYXNzaWZpY2F0aW9ucyA8LSBEaXZpc2lvbl9DbGFzc2lmaWNhdGlvbnMgJT4lIAogIGZpbHRlcihEaXZpc2lvbiAhPSAnVG90YWwgRW5yb2xtZW50JykKYGBgCgpUaGUgZ3JhcGggYmVsb3cgc2hvd3MgdGhhdCB0aGUgYm9vdGhzIHRoYXQgaGF2ZSBhIGxvdyBBTFAgMnBwIGFuZCBhIGxvdyBtZWRpYW4gaW5jb21lIGFyZSBwcmltYXJpbHkgcnVyYWwgYm9vdGhzLiBUaGlzIHJlbGF0aW9uc2hpcCBzZWVtcyBzdHJvbmdlciB0aGFuIHRoZSBMaWIvTmF0IHNwbGl0LgpgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CnBvbGxpbmdfcGxhY2VfMnBwX2NsZWFuICU+JSAKICBtdXRhdGUoRGl2aXNpb24gPSBzdHJpbmdyOjpzdHJfdG9fdGl0bGUoRGl2aXNpb25ObSkpICU+JQogIGlubmVyX2pvaW4oRGl2aXNpb25fQ2xhc3NpZmljYXRpb25zKSAlPiUgCiAgZmlsdGVyKFN0YXRlQWIgPT0gJ05TVycpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBBTFBfUGVyY2VudC8xMDAsIHggPSBtZWRpYW5faG91c2Vob2xkX2luY29tZSwgY29sb3VyID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMSkgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTYpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpkb2xsYXIpICsKICBsYWJzKHRpdGxlID0gJzIwMTYgRWxlY3Rpb246IEFMUCAyIFBhcnR5IFByZWZlcnJlZCBQZXJjZW50YWdlJywgCiAgICAgICB5ID0gJ0FMUCAycHAgUGVyY2VudGFnZScsCiAgICAgICB4ID0gJ0Jvb3RoIE1lZGlhbiBJbmNvbWUnLCBjb2xvdXIgPSAnUmVnaW9uJywKICAgICAgIHN1YnRpdGxlID0gJ2J5IFBvbGxpbmcgQm9vdGgsIFVud2VpZ2h0ZWQgKE5TVyknKQpgYGAKCkxvb2tpbmcgYXQgYWxsIHN0YXRlcyB3ZSBzZWUgYSBzaW1pbGFyIHJlbGF0aW9uc2hpcCwgYWx0aG91Z2ggbGVzcyBzdHJvbmcgdGhhbiBpbiBOU1cuCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KcG9sbGluZ19wbGFjZV8ycHBfY2xlYW4gJT4lIAogIG11dGF0ZShEaXZpc2lvbiA9IHN0cmluZ3I6OnN0cl90b190aXRsZShEaXZpc2lvbk5tKSkgJT4lCiAgaW5uZXJfam9pbihEaXZpc2lvbl9DbGFzc2lmaWNhdGlvbnMpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBBTFBfUGVyY2VudC8xMDAsIHggPSBtZWRpYW5faG91c2Vob2xkX2luY29tZSwgY29sb3VyID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMSkgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTYpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpkb2xsYXIpICsKICBsYWJzKHRpdGxlID0gJzIwMTYgRWxlY3Rpb246IEFMUCAyIFBhcnR5IFByZWZlcnJlZCBQZXJjZW50YWdlJywgeSA9ICdBTFAgMnBwIFBlcmNlbnRhZ2UnLAogICAgICAgeCA9ICdNZWRpYW4gQm9vdGggSW5jb21lJywgY29sb3VyID0gJ1JlZ2lvbicsCiAgICAgICBzdWJ0aXRsZSA9ICdieSBQb2xsaW5nIEJvb3RoLCBVbndlaWdodGVkJykKYGBgCgpXaGF0IGFib3V0IHNvbWUgb2YgdGhlIG90aGVyIHZhcmlhYmxlcz8KCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KcG9sbGluZ19wbGFjZV8ycHBfY2xlYW4gJT4lIAogIG11dGF0ZShEaXZpc2lvbiA9IHN0cmluZ3I6OnN0cl90b190aXRsZShEaXZpc2lvbk5tKSkgJT4lCiAgaW5uZXJfam9pbihEaXZpc2lvbl9DbGFzc2lmaWNhdGlvbnMpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBBTFBfUGVyY2VudC8xMDAsIHggPSBhdmVyYWdlX2hvdXNlaG9sZF9zaXplLCBjb2xvdXIgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX3BvaW50KHNpemUgPSAxKSArCiAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxNikgKyBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnYm90dG9tJykgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgbGFicyh0aXRsZSA9ICcyMDE2IEVsZWN0aW9uOiBBTFAgMiBQYXJ0eSBQcmVmZXJyZWQgUGVyY2VudGFnZScsIHkgPSAnQUxQIDJwcCBQZXJjZW50YWdlJywKICAgICAgIHggPSAnQXZlcmFnZSBIb3VzZWhvbGQgU2l6ZScsIGNvbG91ciA9ICdSZWdpb24nLAogICAgICAgc3VidGl0bGUgPSAnYnkgUG9sbGluZyBCb290aCwgVW53ZWlnaHRlZCcpCmBgYAoKYGBge3IsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIGVycm9yPUYsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpwb2xsaW5nX3BsYWNlXzJwcF9jbGVhbiAlPiUgCiAgbXV0YXRlKERpdmlzaW9uID0gc3RyaW5ncjo6c3RyX3RvX3RpdGxlKERpdmlzaW9uTm0pKSAlPiUKICBpbm5lcl9qb2luKERpdmlzaW9uX0NsYXNzaWZpY2F0aW9ucykgJT4lIAogIGdncGxvdChhZXMoeSA9IEFMUF9QZXJjZW50LzEwMCwgeCA9IHBlcmNlbnRfZmVtYWxlLCBjb2xvdXIgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX3BvaW50KHNpemUgPSAxKSArCiAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxNikgKyBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnYm90dG9tJykgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsKICBsYWJzKHRpdGxlID0gJzIwMTYgRWxlY3Rpb246IEFMUCAyIFBhcnR5IFByZWZlcnJlZCBQZXJjZW50YWdlJywgeSA9ICdBTFAgMnBwIFBlcmNlbnRhZ2UnLAogICAgICAgeCA9ICdQZXJjZW50IEZlbWFsZScsIGNvbG91ciA9ICdSZWdpb24nLAogICAgICAgc3VidGl0bGUgPSAnYnkgUG9sbGluZyBCb290aCwgVW53ZWlnaHRlZCcpCmBgYAoKYGBge3J9CnBvbGxpbmdfcGxhY2VfMnBwX2NsZWFuICU+JSAKICBzZWxlY3QoQUxQX1BlcmNlbnQsIFN3aW5nLCBtZWRpYW5fYWdlLCBtZWRpYW5faG91c2Vob2xkX2luY29tZSwgYXZlcmFnZV9ob3VzZWhvbGRfc2l6ZSwKICAgICAgICAgcGVyc29uc19wZXJfYmVkcm9vbSwgbWVkaWFuX3dlZWtseV9yZW50LCBtZWRpYW5fYW5udWFsX21vcnRnYWdlLAogICAgICAgICBwZXJjZW50X2ZlbWFsZSwgcGVyY2VudF9kZWZhY3RvLCBwZXJjZW50X2Jvcm5faW5fYXVzdHJhbGlhLAogICAgICAgICBwZXJjZW50X3VuaXQsIHBlcmNlbnRfbW9ydGdhZ2UsIHBlcmNlbnRfcmVudCkgJT4lIAogIGNvciAlPiUgCiAga2FibGUoKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KcG9sbGluZ19wbGFjZV8ycHBfY2xlYW4gJT4lIAogIG11dGF0ZShEaXZpc2lvbiA9IHN0cmluZ3I6OnN0cl90b190aXRsZShEaXZpc2lvbk5tKSkgJT4lCiAgaW5uZXJfam9pbihEaXZpc2lvbl9DbGFzc2lmaWNhdGlvbnMpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBBTFBfUGVyY2VudC8xMDAsIHggPSBwZXJzb25zX3Blcl9iZWRyb29tLCBjb2xvdXIgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX3BvaW50KHNpemUgPSAxKSArCiAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemUgPSAxNikgKyBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnYm90dG9tJykgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgbGFicyh0aXRsZSA9ICcyMDE2IEVsZWN0aW9uOiBBTFAgMiBQYXJ0eSBQcmVmZXJyZWQgUGVyY2VudGFnZScsIHkgPSAnQUxQIDJwcCBQZXJjZW50YWdlJywKICAgICAgIHggPSAnUGVyc29ucyBwZXIgQmVkcm9vbScsIGNvbG91ciA9ICdSZWdpb24nLAogICAgICAgc3VidGl0bGUgPSAnYnkgUG9sbGluZyBCb290aCwgVW53ZWlnaHRlZCcpCmBgYAoKYGBge3IsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIGVycm9yPUYsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpwb2xsaW5nX3BsYWNlXzJwcF9jbGVhbiAlPiUgCiAgbXV0YXRlKERpdmlzaW9uID0gc3RyaW5ncjo6c3RyX3RvX3RpdGxlKERpdmlzaW9uTm0pKSAlPiUKICBpbm5lcl9qb2luKERpdmlzaW9uX0NsYXNzaWZpY2F0aW9ucykgJT4lIAogIGdncGxvdChhZXMoeSA9IEFMUF9QZXJjZW50LzEwMCwgeCA9IHBlcmNlbnRfdW5pdCwgY29sb3VyID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMSkgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTYpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgbGFicyh0aXRsZSA9ICcyMDE2IEVsZWN0aW9uOiBBTFAgMiBQYXJ0eSBQcmVmZXJyZWQgUGVyY2VudGFnZScsIHkgPSAnQUxQIDJwcCBQZXJjZW50YWdlJywKICAgICAgIHggPSAnUGVyY2VudCBvZiBEd2VsbGluZ3MgLSBVbml0JywgY29sb3VyID0gJ1JlZ2lvbicsCiAgICAgICBzdWJ0aXRsZSA9ICdieSBQb2xsaW5nIEJvb3RoLCBVbndlaWdodGVkJykKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CnBvbGxpbmdfcGxhY2VfMnBwX2NsZWFuICU+JSAKICBtdXRhdGUoRGl2aXNpb24gPSBzdHJpbmdyOjpzdHJfdG9fdGl0bGUoRGl2aXNpb25ObSkpICU+JQogIGlubmVyX2pvaW4oRGl2aXNpb25fQ2xhc3NpZmljYXRpb25zKSAlPiUgCiAgZ2dwbG90KGFlcyh5ID0gQUxQX1BlcmNlbnQvMTAwLCB4ID0gcGVyY2VudF9tb3J0Z2FnZSwgY29sb3VyID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMSkgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTYpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgbGFicyh0aXRsZSA9ICcyMDE2IEVsZWN0aW9uOiBBTFAgMiBQYXJ0eSBQcmVmZXJyZWQgUGVyY2VudGFnZScsIHkgPSAnQUxQIDJwcCBQZXJjZW50YWdlJywKICAgICAgIHggPSAnUGVyY2VudCBvZiBEd2VsbGluZ3MgLSBVbmRlciBNb3J0Z2FnZScsIGNvbG91ciA9ICdSZWdpb24nLAogICAgICAgc3VidGl0bGUgPSAnYnkgUG9sbGluZyBCb290aCwgVW53ZWlnaHRlZCcpCmBgYAoKYGBge3IsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIGVycm9yPUYsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpwb2xsaW5nX3BsYWNlXzJwcF9jbGVhbiAlPiUgCiAgbXV0YXRlKERpdmlzaW9uID0gc3RyaW5ncjo6c3RyX3RvX3RpdGxlKERpdmlzaW9uTm0pKSAlPiUKICBpbm5lcl9qb2luKERpdmlzaW9uX0NsYXNzaWZpY2F0aW9ucykgJT4lIAogIGdncGxvdChhZXMoeSA9IEFMUF9QZXJjZW50LzEwMCwgeCA9IHBlcmNlbnRfcmVudCwgY29sb3VyID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMSkgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTYpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgbGFicyh0aXRsZSA9ICcyMDE2IEVsZWN0aW9uOiBBTFAgMiBQYXJ0eSBQcmVmZXJyZWQgUGVyY2VudGFnZScsIHkgPSAnQUxQIDJwcCBQZXJjZW50YWdlJywKICAgICAgIHggPSAnUGVyY2VudCBvZiBEd2VsbGluZ3MgLSBSZW50aW5nJywgY29sb3VyID0gJ1JlZ2lvbicsCiAgICAgICBzdWJ0aXRsZSA9ICdieSBQb2xsaW5nIEJvb3RoLCBVbndlaWdodGVkJykKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9NCwgZXJyb3I9RiwgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CnBvbGxpbmdfcGxhY2VfMnBwX2NsZWFuICU+JSAKICBtdXRhdGUoRGl2aXNpb24gPSBzdHJpbmdyOjpzdHJfdG9fdGl0bGUoRGl2aXNpb25ObSkpICU+JQogIGlubmVyX2pvaW4oRGl2aXNpb25fQ2xhc3NpZmljYXRpb25zKSAlPiUgCiAgZ2dwbG90KGFlcyh5ID0gQUxQX1BlcmNlbnQvMTAwLCB4ID0gcGVyY2VudF9pbmRpZywgY29sb3VyID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMSkgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTYpICsgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArCiAgbGFicyh0aXRsZSA9ICcyMDE2IEVsZWN0aW9uOiBBTFAgMiBQYXJ0eSBQcmVmZXJyZWQgUGVyY2VudGFnZScsIHkgPSAnQUxQIDJwcCBQZXJjZW50YWdlJywKICAgICAgIHggPSAnUGVyY2VudCBJbmRpZ2VuZW91cycsIGNvbG91ciA9ICdSZWdpb24nLAogICAgICAgc3VidGl0bGUgPSAnYnkgUG9sbGluZyBCb290aCwgVW53ZWlnaHRlZCcpCmBgYAoKYGBge3IsIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTQsIGVycm9yPUYsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpwb2xsaW5nX3BsYWNlXzJwcF9jbGVhbiAlPiUgCiAgbXV0YXRlKERpdmlzaW9uID0gc3RyaW5ncjo6c3RyX3RvX3RpdGxlKERpdmlzaW9uTm0pKSAlPiUKICBpbm5lcl9qb2luKERpdmlzaW9uX0NsYXNzaWZpY2F0aW9ucykgJT4lIAogIGdncGxvdChhZXMoeSA9IEFMUF9QZXJjZW50LzEwMCwgeCA9IHBlcmNlbnRfYm9ybl9pbl9hdXN0cmFsaWEsIGNvbG91ciA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDEpICsKICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDE2KSArIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIGxhYnModGl0bGUgPSAnMjAxNiBFbGVjdGlvbjogQUxQIDIgUGFydHkgUHJlZmVycmVkIFBlcmNlbnRhZ2UnLCB5ID0gJ0FMUCAycHAgUGVyY2VudGFnZScsCiAgICAgICB4ID0gJ1BlcmNlbnQgQm9ybiBpbiBBdXN0cmFsaWEnLCBjb2xvdXIgPSAnUmVnaW9uJywKICAgICAgIHN1YnRpdGxlID0gJ2J5IFBvbGxpbmcgQm9vdGgsIFVud2VpZ2h0ZWQnKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD00LCBlcnJvcj1GLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KcG9sbGluZ19wbGFjZV8ycHBfY2xlYW4gJT4lIAogIG11dGF0ZShEaXZpc2lvbiA9IHN0cmluZ3I6OnN0cl90b190aXRsZShEaXZpc2lvbk5tKSkgJT4lCiAgaW5uZXJfam9pbihEaXZpc2lvbl9DbGFzc2lmaWNhdGlvbnMpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBBTFBfUGVyY2VudC8xMDAsIHggPSBwZXJjZW50X2RlZmFjdG8sIGNvbG91ciA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDEpICsKICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDE2KSArIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIGxhYnModGl0bGUgPSAnMjAxNiBFbGVjdGlvbjogQUxQIDIgUGFydHkgUHJlZmVycmVkIFBlcmNlbnRhZ2UnLCB5ID0gJ0FMUCAycHAgUGVyY2VudGFnZScsCiAgICAgICB4ID0gJ1BlcmNlbnQgaW4gYSBEZWZhY3RvIFJlbGF0aW9uc2hpcCcsIGNvbG91ciA9ICdSZWdpb24nLAogICAgICAgc3VidGl0bGUgPSAnYnkgUG9sbGluZyBCb290aCwgVW53ZWlnaHRlZCcpCmBgYAoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK